package Backend.Algorithmen;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;

import GUI.Cell;

public class DepthFirst extends SuperAlgo {

	private History history = new History();
	private int visitedcells;

	public DepthFirst(String name) {
		super(name);
	}

	@Override
	public void start(boolean slow) {
		int nextCell[] = null;
		int border = 0;
		long start = System.currentTimeMillis();
		history.add(0, 0);
		grid[history.getLastY()][history.getLastX()].setLeft(false);
		visitedcells=1;
		
		boolean exitset = false;

		while (visitedcells < available_cells && isRunning()) {
			HashMap<Integer, int[]> poss = getAvailablePos(history.getLastX(), history.getLastY());

			if (poss.size() == 0) {
				history.back();
			} else {
				nextCell = getRandomCell(poss);
				int x = nextCell[0];
				int y = nextCell[1];
				border = nextCell[2];

				switch (border) {
				case Cell.TOP:
					grid[history.getLastY()][history.getLastX()].setTop(false);
					grid[y][x].setBottom(false);
					break;
				case Cell.RIGHT:
					grid[history.getLastY()][history.getLastX()].setRight(false);
					grid[y][x].setLeft(false);
					break;
				case Cell.BOTTOM:
					grid[history.getLastY()][history.getLastX()].setBottom(false);
					grid[y][x].setTop(false);
					break;
				case Cell.LEFT:
					grid[history.getLastY()][history.getLastX()].setLeft(false);
					grid[y][x].setRight(false);
					break;

				}
				
				if(!exitset && x == grid[0].length-1){
					grid[y][x].setRight(false);
					exitset = true;
				}
				
				history.add(x, y);
				visitedcells++;

				if (slow) {
					try {
						Thread.currentThread().sleep(getDelay());
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
				double t = (visitedcells  / ((float)(available_cells/100)));
				setStatus((int)t);
				
			}
		}
		setTime(System.currentTimeMillis() - start);
	}

	private int[] getRandomCell(HashMap<Integer, int[]> pos) {
		Random randi = new Random();
		while (true) {
			int rand = randi.nextInt(4);

			if (pos.containsKey(rand)) {
				int[] ret = { pos.get(rand)[0], pos.get(rand)[1], rand };
				return ret;
			}
		}

	}

	private HashMap<Integer, int[]> getAvailablePos(int x, int y) {
		HashMap<Integer, int[]> pos = new HashMap<Integer, int[]>();

		if ((y - 1) > -1)
			if (grid[y - 1][x].wallsIntact())
				pos.put(Cell.TOP, new int[] { x, y - 1 }); // oben

		if ((x + 1) < grid[0].length)
			if (grid[y][x + 1].wallsIntact())
				pos.put(Cell.RIGHT, new int[] { x + 1, y }); // rechts

		if ((y + 1) < grid.length)
			if (grid[y + 1][x].wallsIntact())
				pos.put(Cell.BOTTOM, new int[] { x, y + 1 }); // unten

		if ((x - 1) > -1)
			if (grid[y][x - 1].wallsIntact())
				pos.put(Cell.LEFT, new int[] { x - 1, y }); // link

		return pos;
	}

	public class History {
		private ArrayList<int[]> hist = new ArrayList<int[]>();

		public int[] getLast() {
			return hist.get(hist.size() - 1);
		}

		public int getLastX() {
			return hist.get(hist.size() - 1)[0];
		}

		public int getLastY() {
			return hist.get(hist.size() - 1)[1];
		}

		public void back() {
			hist.remove(hist.size() - 1);
		}

		public void add(int x, int y) {
			hist.add(new int[] { x, y });
		}

		public boolean isEmpty() {
			return hist.isEmpty();
		}

	}

}
